home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / m / mpegplay / mpeg_sys / mpeg_sys.c next >
Encoding:
C/C++ Source or Header  |  1996-11-03  |  21.1 KB  |  765 lines

  1. /* MPEG_SYS - Adaption of READFILE.C from MPEG_STAT 2.1 (see below)
  2.  *           for analyzing and converting MPEG System Layer Streams.
  3.  *          (c) 1995 by Guido Vollbeding.
  4.  *          Ported for Pure-C on Atari TOS.
  5.  *
  6.  * Use with following project file:
  7.  *
  8.  * mpeg_sys.ttp
  9.  * =
  10.  * pcxstart.o
  11.  * mpeg_sys
  12.  * pcfltlib.lib
  13.  * pcstdlib.lib
  14.  * pctoslib.lib
  15.  *
  16.  * ---------------------------
  17.  *
  18.  * MPEGSTAT - analyzing tool for MPEG-I video streams
  19.  *
  20.  * Technical University of Berlin, Germany, Dept. of Computer Science
  21.  * Tom Pfeifer - Multimedia systems project - pfeifer@fokus.gmd.de
  22.  *
  23.  * Jens Brettin, Harald Masche, Alexander Schulze, Dirk Schubert
  24.  *
  25.  * This program uses parts of the source code of the Berkeley MPEG player
  26.  *
  27.  * Copyright (c) 1993 Technical University of Berlin, Germany
  28.  *
  29.  * for the parts of the Berkeley player used:
  30.  *
  31.  * ---------------------------
  32.  *
  33.  * Copyright (c) 1994 The Regents of the University of California.
  34.  * All rights reserved.
  35.  *
  36.  * Permission to use, copy, modify, and distribute this software and its
  37.  * documentation for any purpose, without fee, and without written agreement is
  38.  * hereby granted, provided that the above copyright notice and the following
  39.  * two paragraphs appear in all copies of this software.
  40.  *
  41.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  42.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  43.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  44.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45.  *
  46.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  47.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  48.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  49.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  50.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  51.  */
  52.  
  53. /* Change 0 to 1 if using tos.h */
  54. #if 0
  55. #include <tos.h>
  56. #else
  57. #include <osbind.h>
  58. #endif
  59.  
  60. #include <stdio.h>
  61.  
  62. long ReadStartCode(void);
  63.  
  64. int read_sys(long startCode);
  65.  
  66. void print_stats(void);
  67.  
  68. void ReadPackHeader(double *systemClockTime, unsigned long *muxRate);
  69.  
  70. void ReadSystemHeader(void);
  71.  
  72. int ReadPacket(int packetID);
  73.  
  74. void ReadTimeStamp(
  75.    unsigned char *inputBuffer,
  76.    unsigned char *hiBit,
  77.    unsigned long *low4Bytes);
  78.  
  79. void ReadSTD(
  80.    unsigned char *inputBuffer,
  81.    unsigned char *stdBufferScale,
  82.    unsigned long *stdBufferSize);
  83.  
  84. void ReadRate(
  85.    unsigned char *inputBuffer,
  86.    unsigned long *rate);
  87.  
  88. void MakeFloatClockTime(
  89.    unsigned char hiBit,
  90.    unsigned long low4Bytes,
  91.    double *floatClockTime);
  92.  
  93. /* Silly Constants.... */
  94. #define START_CODE_PREFIX        0x00000100L
  95. #define ISO_11172_END_CODE       0x000001b9L
  96. #define PACK_START_CODE          0x000001baL
  97. #define SYSTEM_HEADER_START_CODE 0x000001bbL
  98.  
  99. #define PACK_HEADER_SIZE   8
  100. #define SYSTEM_HEADER_SIZE 6
  101.  
  102. #define STD_AUDIO_STREAM_ID 0xb8
  103. #define STD_VIDEO_STREAM_ID 0xb9
  104. #define MIN_STREAM_ID_ID    0xbc
  105. #define RESERVED_STREAM_ID  0xbc
  106. #define PRIVATE_STREAM_1_ID 0xbd
  107. #define PADDING_STREAM_ID   0xbe
  108. #define PRIVATE_STREAM_2_ID 0xbf
  109.  
  110. #define STD_SYSTEM_CLOCK_FREQ 90000L
  111. #define MUX_RATE_SCALE_FACTOR 50
  112. #define MAX_STREAMS 8
  113.  
  114.  
  115. /*  GV: The following stuff is for much more efficient file i/o
  116.  *    than the standard library functions...
  117.  */
  118.  
  119. #define BUF_LENGTH 80L*1024
  120.  
  121. typedef struct
  122. {
  123.   unsigned char *pbuf;
  124.   long          bytes_left, length;
  125.   int        handle, EOF_flag;
  126.   unsigned char fbuf[BUF_LENGTH];
  127. }
  128. FBUF;
  129.  
  130. void Fbufread(FBUF *fp)
  131. {
  132.   long count;
  133.  
  134.   if (fp->EOF_flag) goto eof;
  135.  
  136.   if ((count = Fread(fp->handle, BUF_LENGTH, fp->fbuf)) > 0)
  137.     fp->length += count;
  138.   else
  139.   {
  140.     fp->EOF_flag++;
  141.     /*
  142.        Make 32 bits equal to sys end code
  143.        in order to prevent messy data
  144.        from infinite recursion.
  145.     */
  146.     *(long *)fp->fbuf = ISO_11172_END_CODE;
  147.     eof:
  148.     count = 4;
  149.   }
  150.   fp->bytes_left += count;
  151.   fp->pbuf = fp->fbuf;
  152. }
  153.  
  154. void Fbufwrite(FBUF *fp)
  155. {
  156.   long count;
  157.  
  158.   count = BUF_LENGTH;
  159.   if (count -= fp->bytes_left)
  160.   {
  161.     fp->pbuf = fp->fbuf;
  162.     fp->bytes_left += count;
  163.     if (fp->EOF_flag) return;
  164.     fp->length += count;
  165.     if (Fwrite(fp->handle, count, fp->fbuf) != count)
  166.       fp->EOF_flag++;
  167. } }
  168.  
  169. #define MAKESTMT(stuff)      do { stuff } while (0)
  170.  
  171. #define FGETC(fp, dest)   \
  172.   MAKESTMT( if (--(fp)->bytes_left < 0) Fbufread(fp); \
  173.         dest = *(fp)->pbuf++; )
  174.  
  175. #define FSKIPC(fp)   \
  176.   MAKESTMT( if (--(fp)->bytes_left < 0) Fbufread(fp); \
  177.         (fp)->pbuf++; )
  178.  
  179. #define FCOPYC(src, des)   \
  180.   MAKESTMT( if (--(src)->bytes_left < 0) Fbufread(src); \
  181.         *(des)->pbuf++ = *(src)->pbuf++; \
  182.         if (--(des)->bytes_left == 0) Fbufwrite(des); )
  183.  
  184.  
  185. /* Global file struct to incoming data. */
  186. FBUF input;
  187.  
  188. FILE *syslogOutput = 0;
  189.  
  190. FBUF output;
  191.  
  192. void Usage(void)
  193. {
  194.   fprintf(stderr, "Usage:  mpeg_sys [-l] [input] [output]\n");
  195.   fprintf(stderr, "option -l:\n");
  196.   fprintf(stderr, "\tPut logging of system layer parsing to stdout.\n");
  197.   fprintf(stderr, "input:\n");
  198.   fprintf(stderr, "\tMPEG System Layer Stream.\n");
  199.   fprintf(stderr, "output:\n");
  200.   fprintf(stderr, "\tMPEG Video Stream extracted from input.\n");
  201. }
  202.  
  203. int main(int argc, char **argv)
  204. {
  205.   long data;
  206.  
  207.   fprintf(stdout,
  208.     "\nMPEG_SYS " __DATE__ " -- Tool for MPEG-1 System Layer Streams.\n\n");
  209.  
  210.   if (--argc <= 0) {
  211.     Usage(); return 0;
  212.   }
  213.   ++argv;
  214.   if (argv[0][0] == '-') {
  215.     if (argv[0][1] == 'l' || argv[0][1] == 'L')
  216.       syslogOutput = stdout;
  217.     else
  218.       fprintf(stderr, "Ignoring invalid option %s\n", argv[0]);
  219.     if (--argc <= 0) {
  220.       Usage(); return 0;
  221.     }
  222.     ++argv;
  223.   }
  224.  
  225.   if ((input.handle = Fopen(argv[0], 0)) < 0) {
  226.     fprintf(stderr, "Can't open input file %s\n", argv[0]);
  227.     return 1;
  228.   }
  229.   input.bytes_left = 0; input.length = 0; input.EOF_flag = 0;
  230.  
  231.   data = ReadStartCode();
  232.   if (data != PACK_START_CODE && data != SYSTEM_HEADER_START_CODE) {
  233.     fprintf(stderr, "This is not an MPEG System Layer Stream!\n");
  234.     return 0;
  235.   }
  236.   /* Yow, a System Layer Stream.  Much harder to parse.  Call in the
  237.      specialist.... */
  238.   fprintf(stderr, "This is an MPEG System Layer Stream.  "
  239.           "Audio is not analyzed.\n");
  240.  
  241.   output.handle = -1;
  242.   if (--argc > 0) {
  243.     if ((output.handle = Fcreate(argv[1], 0)) < 0) {
  244.       fprintf(stderr, "Can't create output file %s\n", argv[1]);
  245.       return 1;
  246.     }
  247.     output.bytes_left = sizeof(output.fbuf);
  248.     output.pbuf = output.fbuf;
  249.     output.length = 0;
  250.     output.EOF_flag = 0;
  251.   }
  252.  
  253.   /* OK, here's the real work... */
  254.   while (read_sys(data))
  255.     data = ReadStartCode();
  256.  
  257.   /* Done. Check for errors... */
  258.   data = 0;
  259.   if (input.EOF_flag) {
  260.     data = 1;
  261.     fprintf(stderr,
  262.       "Warning: Read Error or Premature EOF encountered in input stream!\n");
  263.   }
  264.   if (output.handle >= 0) {
  265.     Fbufwrite(&output); /* Flush out last bytes from buffer. */
  266.     if (output.EOF_flag) {
  267.       data = 1;
  268.       fprintf(stderr, "Warning: Write Error occured in output file!\n");
  269.     }
  270.     if (Fclose(output.handle)) {
  271.       data = 1;
  272.       fprintf(stderr, "Warning: Error in closing output file!\n");
  273.     }
  274.   }
  275.   if (data == 0) fprintf(stderr, "Successful parse of MPEG system level.\n");
  276.  
  277.   /* Print statistics and bye... */
  278.   print_stats(); return 0;
  279. }
  280.  
  281.  
  282. /*
  283.   Here is the specialist....
  284.   Code is adapted from our program demux....
  285.   */
  286.  
  287.  
  288. /* Statistics */
  289. static long gNumAudioPackets;
  290. static long gNumVideoPackets;
  291. static long gNumPaddingPackets;
  292. static long gNumReservedPackets;
  293. static long gNumPrivate_1_Packets;
  294. static long gNumPrivate_2_Packets;
  295.  
  296. static long numPacks;
  297. static long numPackets;
  298. static long numSystemHeaders;
  299.  
  300. static long audBytes;
  301. static long vidBytes;
  302. static long sysBytes;
  303.  
  304. /* Stream IDs */
  305. static int gAudioStreamID;
  306. static int gVideoStreamID;
  307. static int gReservedStreamID;
  308.  
  309.  
  310. /*
  311.  *-----------------------------------------------------------
  312.  *
  313.  *  ReadStartCode
  314.  *
  315.  *      Parses a start code out of the stream
  316.  *
  317.  *  Results:  start code
  318.  *
  319.  *  GV: I hacked this code for searching the next REAL
  320.  *    start code (0x000001xx) in the same manner like
  321.  *    next_start_code() does it in the video decoder.
  322.  *    This seems more reliable (avoids hang-ups in read_sys)
  323.  *    and more flexible (skipping stuffing bytes).
  324.  *
  325.  *-----------------------------------------------------------
  326.  */
  327. long ReadStartCode(void)
  328. {
  329.   long startCode;
  330.  
  331.   FGETC(&input, (char)startCode); startCode <<= 8;
  332.   FGETC(&input, (char)startCode); startCode <<= 8;
  333.   FGETC(&input, (char)startCode); startCode <<= 8;
  334.   while (startCode != START_CODE_PREFIX) {
  335.     FGETC(&input, (char)startCode); startCode <<= 8;
  336.     sysBytes++;
  337.   }
  338.   FGETC(&input, (char)startCode); sysBytes += 4;
  339.   if (syslogOutput) {
  340.     fprintf(syslogOutput, "Read start code: %08lx\n", startCode);
  341.   }
  342.   return startCode;
  343. }
  344.  
  345. /*
  346.  *----------------------------------------------------------
  347.  *
  348.  *  read_sys
  349.  *
  350.  *      Parse out a packet of the system layer MPEG file.
  351.  *
  352.  *  Results:  Returns 0 if error or EOF
  353.  *            Returns 1 if more data read
  354.  *
  355.  *----------------------------------------------------------
  356.  */
  357. int read_sys(long startCode)
  358. {
  359.   double systemClockTime;
  360.   unsigned long muxRate;
  361.  
  362.   while (startCode != ISO_11172_END_CODE) {
  363.     if (startCode == PACK_START_CODE) {
  364.       ++numPacks;
  365.       if (syslogOutput) {
  366.     fprintf(syslogOutput, "PACK #%ld:\n", numPacks);
  367.       }
  368.       ReadPackHeader(&systemClockTime, &muxRate);
  369.     }
  370.     else if (startCode == SYSTEM_HEADER_START_CODE) {
  371.       ++numSystemHeaders;
  372.       if (syslogOutput) {
  373.     fprintf(syslogOutput, "SYSTEM HEADER #%ld:\n", numSystemHeaders);
  374.       }
  375.       ReadSystemHeader();
  376.     }
  377.     else {
  378.       ++numPackets;
  379.       if (syslogOutput) {
  380.     fprintf(syslogOutput, "PACKET #%ld:\n", numPackets);
  381.       }
  382.       if (ReadPacket((int)startCode & 0xff)) return 1;
  383.     }
  384.     startCode = ReadStartCode();
  385.   }
  386.   return 0;
  387. }
  388.  
  389. void print_stats(void)
  390. {
  391.   fprintf(stdout, "%ld system headers, %ld packs, %ld packets\n",
  392.       numSystemHeaders, numPacks, numPackets);
  393.   fprintf(stdout, "%ld audio packets, %ld video packets, %ld padding packets\n",
  394.       gNumAudioPackets, gNumVideoPackets, gNumPaddingPackets);
  395.   fprintf(stdout, "%ld reserved packets, %ld/%ld private type 1/2 packets\n",
  396.       gNumReservedPackets, gNumPrivate_1_Packets, gNumPrivate_2_Packets);
  397.   fprintf(stdout, "%ld audio bytes, %ld video bytes, %ld system bytes\n",
  398.       audBytes, vidBytes, sysBytes);
  399. }
  400.  
  401. /*
  402.  *-----------------------------------------------------------------
  403.  *
  404.  *  ReadPackHeader
  405.  *
  406.  *      Parses out the PACK header
  407.  *
  408.  *-------------------------------------------------------------------
  409.  */
  410. void ReadPackHeader(double *systemClockTime, unsigned long *muxRate)
  411. {
  412.   long numRead;
  413.   unsigned char inputBuffer[PACK_HEADER_SIZE];
  414.   unsigned long systemClockRef;
  415.   unsigned char systemClockRefHiBit;
  416.  
  417.   for (numRead = 0; numRead < PACK_HEADER_SIZE; numRead++)
  418.     FGETC(&input, inputBuffer[numRead]);
  419.   sysBytes += numRead;
  420.   ReadTimeStamp(inputBuffer, &systemClockRefHiBit, &systemClockRef);
  421.   MakeFloatClockTime(systemClockRefHiBit, systemClockRef, systemClockTime);
  422.   ReadRate(&inputBuffer[5], muxRate);
  423.   *muxRate *= MUX_RATE_SCALE_FACTOR;
  424.   if (syslogOutput) {
  425.     fprintf(syslogOutput, "System clock reference: %d, %lu (0x%x%08lx)\n",
  426.         (int)systemClockRefHiBit, systemClockRef,
  427.         (int)systemClockRefHiBit, systemClockRef);
  428.     fprintf(syslogOutput, "System clock time: %1.4lf\n", *systemClockTime);
  429.     fprintf(syslogOutput, "muxRate: %lu (0x%08lx)\n", *muxRate, *muxRate);
  430.   }
  431. }
  432.  
  433. /*
  434.  *------------------------------------------------------------------
  435.  *
  436.  *   ReadSystemHeader
  437.  *
  438.  *      Parse out the system header, setup out stream IDs for parsing packets
  439.  *
  440.  *   Results:  Sets gAudioStreamID and gVideoStreamID
  441.  *
  442.  *------------------------------------------------------------------
  443.  */
  444. void ReadSystemHeader(void)
  445. {
  446.   unsigned char inputBuffer[SYSTEM_HEADER_SIZE];
  447.   long pos, i, headerSize;
  448.   int streamID;
  449.   /* Only needed for system log file */
  450.   unsigned long rateBound;
  451.   unsigned long audioBound;
  452.   unsigned char fixedFlag;
  453.   unsigned char cspsFlag;
  454.   unsigned long videoBound;
  455.   unsigned char sysAudioLockFlag;
  456.   unsigned char sysVideoLockFlag;
  457.   unsigned char stdBufferScale;
  458.   unsigned long stdBufferSize;
  459.  
  460.   FGETC(&input, headerSize); headerSize <<= 8;
  461.   FGETC(&input, (char)headerSize);
  462.   sysBytes += headerSize;
  463.   pos = SYSTEM_HEADER_SIZE; if (headerSize < pos) pos = headerSize;
  464.   for (i = 0; i < pos; i++)
  465.     FGETC(&input, inputBuffer[i]);
  466.   if (syslogOutput) {
  467.     for(i = 0; i < pos; i++)
  468.       fprintf(syslogOutput, "%x ", inputBuffer[i]);
  469.     fprintf(syslogOutput,"\n");
  470.  
  471.     if (headerSize > 4) {
  472.       ReadRate(&inputBuffer[0], &rateBound);
  473.       rateBound *= MUX_RATE_SCALE_FACTOR;
  474.       fprintf(syslogOutput, "rate_bound: %lu (0x%08lx)\n", rateBound, rateBound);
  475.       audioBound = (unsigned long)inputBuffer[3] >> 2;
  476.       fprintf(syslogOutput, "audio_bound: %lu (0x%08lx)\n", audioBound, audioBound);
  477.       fixedFlag = (inputBuffer[3] >> 1) & 0x01;
  478.       fprintf(syslogOutput, "fixed_flag: %d\n", fixedFlag);
  479.       cspsFlag = inputBuffer[3] & 0x01;
  480.       fprintf(syslogOutput, "CSPS_flag: %d\n", cspsFlag);
  481.       videoBound = (unsigned long)inputBuffer[4] & 0x1f;
  482.       fprintf(syslogOutput, "video_bound: %lu (0x%08lx)\n", videoBound, videoBound);
  483.       sysAudioLockFlag = (inputBuffer[4] & 0x80) >> 7;
  484.       fprintf(syslogOutput, "system_audio_lock_flag: %d\n", sysAudioLockFlag);
  485.       sysVideoLockFlag = (inputBuffer[4] & 0x40) >> 6;
  486.       fprintf(syslogOutput, "system_video_lock_flag: %d\n", sysVideoLockFlag);
  487.     }
  488.   }
  489.   headerSize -= pos;
  490.   while (--headerSize >= 0) {
  491.     FGETC(&input, streamID);
  492.     if ((char)streamID >= 0) break;
  493.     if (--headerSize >= 0) FGETC(&input, inputBuffer[1]);
  494.     if (--headerSize >= 0) FGETC(&input, inputBuffer[2]);
  495.     if (syslogOutput) {
  496.       ReadSTD(&inputBuffer[1], &stdBufferScale, &stdBufferSize);
  497.       fprintf(syslogOutput,
  498.               "Read STD_buffer_scale = %d, STD_buffer_size = %lu (0x%0lx)\n",
  499.               (int)stdBufferScale, stdBufferSize, stdBufferSize);
  500.       fprintf(syslogOutput, "System Header: stream with ID 0x%x\n", streamID);
  501.     }
  502.     switch (streamID) {
  503.     case STD_VIDEO_STREAM_ID:
  504.       if (syslogOutput) {
  505.     fprintf(syslogOutput, "System Header: Std video stream\n");
  506.       }
  507.       break;
  508.     case STD_AUDIO_STREAM_ID:
  509.       if (syslogOutput) {
  510.     fprintf(syslogOutput, "System Header: Std audio stream\n");
  511.       }
  512.       break;
  513.     case RESERVED_STREAM_ID:
  514.       if (syslogOutput) {
  515.     fprintf(syslogOutput, "System Header: Reserved stream\n");
  516.       }
  517.       break;
  518.     case PADDING_STREAM_ID:
  519.       if (syslogOutput) {
  520.     fprintf(syslogOutput, "System Header: Padding stream\n");
  521.       }
  522.       break;
  523.     case PRIVATE_STREAM_1_ID:
  524.       if (syslogOutput) {
  525.     fprintf(syslogOutput, "System Header: Private (1) stream\n");
  526.       }
  527.       break;
  528.     case PRIVATE_STREAM_2_ID:
  529.       if (syslogOutput) {
  530.     fprintf(syslogOutput, "System Header: Private (2) stream\n");
  531.       }
  532.       break;
  533.     default:
  534.       if (streamID < MIN_STREAM_ID_ID) {
  535.     if (syslogOutput) {
  536.       fprintf(syslogOutput, "System Header: Illegal stream ID\n");
  537.     }
  538.     break;
  539.       }
  540.       switch (streamID >> 4) {
  541.       case 0xc:
  542.       case 0xd:
  543.     if (syslogOutput) {
  544.       fprintf(syslogOutput, "System Header: audio stream #%d\n",
  545.           (streamID & 0x1f));
  546.     }
  547.     gAudioStreamID = streamID;
  548.     break;
  549.       case 0xe:
  550.     if (syslogOutput) {
  551.       fprintf(syslogOutput, "System Header: video stream #%d\n",
  552.           (streamID & 0xf));
  553.     }
  554.     if (gVideoStreamID != 0 && gVideoStreamID != streamID) {
  555.       fprintf(stderr, "This program can only handle a single video stream\n");
  556.       break;
  557.     }
  558.     gVideoStreamID = streamID;
  559.     break;
  560.       case 0xf:
  561.     gReservedStreamID = streamID;
  562.     if (syslogOutput) {
  563.       fprintf(syslogOutput, "System Header: reserved stream #%d\n",
  564.           (streamID & 0xf));
  565.     }
  566.     break;
  567.       }
  568.       break;
  569.     }
  570.   }
  571.   while (--headerSize >= 0) FSKIPC(&input);
  572. }
  573.  
  574. /*
  575.  *-----------------------------------------------------------------
  576.  *
  577.  *  ReadPacket
  578.  *
  579.  *      Reads a single packet out of the stream, and puts it in the
  580.  *      buffer if it is video.
  581.  *
  582.  *  Results:  Returns: 0 - not video packet we want
  583.  *               1 - got video packet into buffer
  584.  *
  585.  *  GV: In difference to the original code, received audio packets
  586.  *      are not signalled to the caller.
  587.  *      But the code for checking of audio is left here, so it can
  588.  *      be simply extended for audio support. At the moment, audio
  589.  *      is skipped over.
  590.  *
  591.  *-----------------------------------------------------------------
  592.  */
  593. int ReadPacket(int packetID)
  594. {
  595.   unsigned char nextByte;
  596.   unsigned short packetLength;
  597.   int pos, i;
  598.  
  599.   FGETC(&input, (char)packetLength); packetLength <<= 8;
  600.   FGETC(&input, (char)packetLength);
  601.   if (syslogOutput) {
  602.     fprintf(syslogOutput,
  603.         "input packet with ID %02x has length = %u at file offset %ld\n",
  604.         packetID, packetLength, input.length - input.bytes_left);
  605.   }
  606.   if (packetID == gAudioStreamID) {
  607.     ++gNumAudioPackets;
  608.   }
  609.   else if (packetID == gVideoStreamID) {
  610.     ++gNumVideoPackets;
  611.   }
  612.   else {
  613.     switch (packetID) {
  614.     case PADDING_STREAM_ID:
  615.       if (syslogOutput) {
  616.     fprintf(syslogOutput, "Padding packet.\n");
  617.       }
  618.       ++gNumPaddingPackets;
  619.       break;
  620.     case RESERVED_STREAM_ID:
  621.       if (syslogOutput) {
  622.     fprintf(syslogOutput, "Reserved packet.\n");
  623.       }
  624.       ++gNumReservedPackets;
  625.       break;
  626.     case PRIVATE_STREAM_1_ID:
  627.       if (syslogOutput) {
  628.     fprintf(syslogOutput, "Private packet type 1.\n");
  629.       }
  630.       ++gNumPrivate_1_Packets;
  631.       break;
  632.     case PRIVATE_STREAM_2_ID:
  633.       if (syslogOutput) {
  634.     fprintf(syslogOutput, "Private packet type 2.\n");
  635.       }
  636.       ++gNumPrivate_2_Packets;
  637.       break;
  638.     default:
  639.       fprintf(stderr, "Unknown packet type encountered. P'bly audio.\n");
  640.     }
  641.     if (syslogOutput) {
  642.       fprintf(syslogOutput, "Skipping over this packet.\n");
  643.     }
  644.     sysBytes += packetLength;
  645.     do FSKIPC(&input);
  646.     while (--packetLength);
  647.     return 0;
  648.   }
  649.   FGETC(&input, nextByte);
  650.   pos = 0;
  651.   while ((char)nextByte < 0) {
  652.     if (syslogOutput) {
  653.       if (nextByte != 0xff)
  654.     fprintf(syslogOutput, "Warning: stuffing byte = 0x%x not 0xff\n",
  655.         (int)nextByte);
  656.     }
  657.     pos++;
  658.     FGETC(&input, nextByte);
  659.   }
  660.   if (pos > 0)
  661.     if (syslogOutput) {
  662.       fprintf(syslogOutput, "Skipped %d stuffing bytes\n", pos);
  663.     }
  664.   if ((nextByte >> 6) == 0x01) {
  665.     pos += 2;
  666.     FSKIPC(&input);
  667.     FGETC(&input, nextByte);
  668.   }
  669.   if ((nextByte >> 4) == 0x02) {
  670.     pos += 5;
  671.     i = 4; do FSKIPC(&input); while (--i);
  672.   }
  673.   else if ((nextByte >> 4) == 0x03) {
  674.     pos += 10;
  675.     i = 9; do FSKIPC(&input); while (--i);
  676.   }
  677.   else {
  678.     pos++;
  679.     if (syslogOutput) {
  680.       fprintf(syslogOutput, "Read 0x%02x (s.b. 0x0f)\n", nextByte);
  681.     }
  682.   }
  683.   sysBytes += pos; packetLength -= pos;
  684.   if (packetID == gVideoStreamID) {
  685.     vidBytes += packetLength;
  686.     if (syslogOutput) {
  687.       fprintf(syslogOutput, "Keeping Video packet of length %u\n",
  688.               packetLength);
  689.     }
  690.     if (output.handle >= 0) {
  691.       do FCOPYC(&input, &output);
  692.       while (--packetLength);
  693.     }
  694.     else {
  695.       do FSKIPC(&input);
  696.       while (--packetLength);
  697.     }
  698.     return 1;
  699.   }
  700.   if (packetID == gAudioStreamID) {
  701.     audBytes += packetLength;
  702.     if (syslogOutput) {
  703.       fprintf(syslogOutput, "Receiving Audio packet of length %u\n",
  704.           packetLength);
  705.     }
  706.     do FSKIPC(&input);
  707.     while (--packetLength);
  708.   }
  709.   return 0;
  710. }
  711.  
  712.  
  713. /*
  714.  * The remaining procedures are formatting utility procedures.
  715.  */
  716. void ReadTimeStamp(
  717.      unsigned char *inputBuffer,
  718.      unsigned char *hiBit,
  719.      unsigned long *low4Bytes)
  720. {
  721.   *hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
  722.   *low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
  723.   *low4Bytes |= (unsigned long)inputBuffer[1] << 22;
  724.   *low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
  725.   *low4Bytes |= (unsigned long)inputBuffer[3] << 7;
  726.   *low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
  727. }
  728.  
  729. void ReadSTD(
  730.      unsigned char *inputBuffer,
  731.      unsigned char *stdBufferScale,
  732.      unsigned long *stdBufferSize)
  733. {
  734.   *stdBufferScale = ((inputBuffer[0] & 0x20) >> 5);
  735.   *stdBufferSize = ((unsigned long)inputBuffer[0] & 0x1f) << 8;
  736.   *stdBufferSize |= (unsigned long)inputBuffer[1];
  737. }
  738.  
  739.  
  740. void ReadRate(
  741.      unsigned char *inputBuffer,
  742.      unsigned long *rate)
  743. {
  744.   *rate = (inputBuffer[0] & 0x7f) << 15;
  745.   *rate |= inputBuffer[1] << 7;
  746.   *rate |= (inputBuffer[2] & 0xfe) >> 1;
  747. }
  748.  
  749. #define FLOAT_0x10000 (double)((unsigned long)1 << 16)
  750.  
  751. void MakeFloatClockTime(
  752.      unsigned char hiBit,
  753.      unsigned long low4Bytes,
  754.      double *floatClockTime)
  755. {
  756.   if (hiBit != 0 && hiBit != 1) {
  757.     *floatClockTime = 0.0;
  758.   }
  759.   else {
  760.     *floatClockTime
  761.       = (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
  762.     *floatClockTime /= (double)STD_SYSTEM_CLOCK_FREQ;
  763.   }
  764. }
  765.